package com.bigshen.spring.framework.beans.support;

import com.bigshen.spring.framework.annonation.Controller;
import com.bigshen.spring.framework.annonation.Service;
import com.bigshen.spring.framework.beans.config.BeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @Author eddy.shen
 * @Date 2020/4/18 11:27
 **/
public class BeanDefinitionReader {

    private Properties properties = new Properties();
    private List<String> registryBeanClasses = new ArrayList<>();

    public BeanDefinitionReader(String... configLocations) {

        // 解析配置文件(以一个为例)
        try {
            doLoadConfig(configLocations[0]);
            // 扫描类
            doScanPath(properties.getProperty("scanPackage"));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public Properties getConfig() {
        return properties;
    }

    private void doScanPath(String scanPackage) {

        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));
        File rootFile = new File(url.getFile());

        // 遍历根目录下的所有.class文件，如果有Annonation则为需要交由Spring管理的类
        for (File element : rootFile.listFiles()) {

            if (element.isDirectory()) {
                // 文件夹、递归
                doScanPath(scanPackage + "." + element.getName());
            } else {
                // 文件
                if (!element.getName().endsWith(".class")) {continue;}

                String clazzName = scanPackage + "." + element.getName().replace(".class", "");
                try {
                    Class clazz = Class.forName(clazzName);
                    Boolean isIOCClazz = clazz.isAnnotationPresent(Controller.class)
                            || clazz.isAnnotationPresent(Service.class);
                    if (isIOCClazz) {
                        //统计需要放入IOC容器的class
                        registryBeanClasses.add(clazzName);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

            }

        }

    }

    private void doLoadConfig(String configLocation) {

        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(configLocation.replace("classpath:", ""));
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public List<BeanDefinition> doLoadBeanDefinition() {

        List<BeanDefinition> resultList = new ArrayList<>();

        try {

            if (registryBeanClasses.size() == 0) {
                return resultList;
            }

            for (String className : registryBeanClasses) {

                String beanName = "";

                Class clazz = Class.forName(className);
                // 解析class，转为BeanDefinition
                // BeanDefinition name有三种情况


                // 1. 使用注解value值作为beanName
                if (clazz.isAnnotationPresent(Controller.class)) {
                    Controller annonation = (Controller) clazz.getAnnotation(Controller.class);
                    String annonationValue = annonation.value();
                    if (annonationValue != null && !annonationValue.trim().equals("")) {
                        beanName = annonationValue;
                    }
                }
                if (clazz.isAnnotationPresent(Service.class)) {
                    Service annonation = (Service) clazz.getAnnotation(Service.class);
                    String annonationValue = annonation.value();
                    if (annonationValue != null && !annonationValue.trim().equals("")) {
                        beanName = annonationValue;
                    }
                }

                // 2. 使用类名小写作为BeanName
                if (beanName.trim().equals("")) {
                    beanName = toLowerFirstCase(clazz.getSimpleName());
                }

                BeanDefinition beanDefinition = doCreateBeanDefinition(beanName, className);
                resultList.add(beanDefinition);

                // 3. 针对接口，使用接口类型作为BeanName
                for (Class interfaceClazz : clazz.getInterfaces()) {
                    resultList.add(doCreateBeanDefinition(interfaceClazz.getName(), className));
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultList;
    }

    private BeanDefinition doCreateBeanDefinition(String beanName, String beanClass) {
        BeanDefinition definition = new BeanDefinition();
        definition.setFactoryBeanName(beanName);
        definition.setBeanClassName(beanClass);
        return definition;
    }


    /**
     * 字符首字母小写
     * @param simpleName
     * @return
     */
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
//        if(chars[0] > )
        chars[0] += 32;
        return String.valueOf(chars);
    }


}
